package uk.co.BexhillWeb.MediaManager;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

import org.json.JSONArray;
import org.json.JSONObject;

@SuppressWarnings("serial")
public class SongItem extends JPanel {
	
	private ImageIcon[] imagesFound;
	//private ImageIcon currentImage;
	private int selectedImage =0;
	private ImageIcon selectedImageIcon;
	private JLabel amount = new JLabel();
	private JLabel currentImg = new JLabel();
	private String album = "";
	private String artist = "";
	
	public SongItem(String artistName, String albumName) {
		
		GridBagConstraints c = new GridBagConstraints();
		this.setLayout(new GridBagLayout());
		
		
		
		this.artist = artistName;
		this.album = albumName;
		
		try {
			imagesFound = generateImages(artistName.replace(" ", "+"),albumName.replace(" ", "+"));
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		
		JLabel artName = new JLabel(artist);
		JLabel albName = new JLabel(album);
		
		c.gridx=0;
		c.gridy=1;
		c.gridwidth=4;
		c.gridheight=1;
		this.add(artName, c);
		c.gridx=0;
		c.gridy=2;
		c.gridwidth=4;
		c.gridheight=1;
		this.add(albName, c);
		
		selectedImageIcon = new ImageIcon();
		if(imagesFound.length>0)
			selectedImageIcon = imagesFound[selectedImage];
		currentImg = new JLabel();
		currentImg.setIcon(selectedImageIcon);
		currentImg.setMinimumSize(new Dimension(100,100));
		currentImg.setMaximumSize(new Dimension(100,100));
		currentImg.setPreferredSize(new Dimension(100,100));
		amount.setText("Image "+(selectedImage + 1) + " of " + imagesFound.length);
		
		JButton prev = new JButton("<");
		JButton next = new JButton(">");
		prev.setMinimumSize(new Dimension(20,20));
		prev.setMaximumSize(new Dimension(20,20));
		prev.setPreferredSize(new Dimension(20,20));
		next.setMinimumSize(new Dimension(20,20));
		next.setMaximumSize(new Dimension(20,20));
		next.setPreferredSize(new Dimension(20,20));
		c.gridx=0;
		c.gridy=3;
		c.gridwidth=1;
		c.gridheight=1;
		this.add(prev, c);
		c.gridx=1;
		c.gridy=0;
		c.gridwidth=2;
		c.gridheight=1;
		this.add(currentImg, c);
		c.gridx=1;
		c.gridy=3;
		c.gridwidth=2;
		c.gridheight=1;
		this.add(amount, c);
		c.gridx=3;
		c.gridy=3;
		c.gridwidth=1;
		c.gridheight=1;
		this.add(next, c);
		prev.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
            	selectedImage--;
            	if(selectedImage < 0)
            		selectedImage = 0;
            	selectedImageIcon = imagesFound[selectedImage];
            	currentImg.setIcon(selectedImageIcon);
            	amount.setText("Image "+(selectedImage + 1) + " of " + imagesFound.length);
            }
		});
		
		next.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
            	selectedImage++;
            	if(selectedImage > imagesFound.length - 1)
            		selectedImage = imagesFound.length - 1;
            	
            	selectedImageIcon = imagesFound[selectedImage];
            	currentImg.setIcon(selectedImageIcon);
            	amount.setText("Image "+(selectedImage + 1) + " of " + imagesFound.length);
            }
		});
	}
	
	private ImageIcon getAlbumArt(InputStream fs,long fsPos) throws UnsupportedEncodingException, IOException {
		
		String mimeType;
		byte[] imageData = null;
	    boolean foundImage = false;
	    //mimeType = null;
	    while (!foundImage)
	    {
	    	byte[] buffer = new byte[10];
	    	fs.mark(10);
	    	if ((fs.read(buffer, 0, 10) != 10) || !(new String(buffer, 0, 3, "UTF-8").equals("ID3")))
	        {
	    		fs.reset();
				break;
	        }
	    	fsPos += 10;
	    	int majorVersion = buffer[3] & 0xFF;
	        byte minorVersion = buffer[4];
	        byte[] destinationArray = new byte[4];
	        System.arraycopy(buffer, 6, destinationArray, 0, 4);
	        //Read a 28bit int for size
	        int size = (((((destinationArray[0] & 0xFF) << 0x15) | ((destinationArray[1] & 0xFF) << 14)) | ((destinationArray[2] & 0xFF) << 7)) | (destinationArray[3] & 0xFF));
	        long end = fsPos + size;
	        fs.mark((int)size);
	        long dataLength = end - 11L;
	        
	        boolean ver2 = true;

	        if (majorVersion == 2)
	        {
	            //ID3 v2.2
	            ver2 = true;
	        }
	        else if (majorVersion == 3 || majorVersion == 4)
	        {
	            //ID3 v2.3/ID3 v2.4

	            //Extra data seems might exist, go through
	            boolean hasExtendedHeader = (buffer[5] & 0x40) == 0x40;
	            if (hasExtendedHeader)
	            {
	                byte[] exHeadBuf = new byte[4];
	                fs.read(exHeadBuf, 0, 4);
	                fsPos += 4;
	                int exHeadLength = (((((exHeadBuf[0] & 0xFF) << 0x18) | ((exHeadBuf[1] & 0xFF) << 0x10)) | ((exHeadBuf[2] & 0xFF) << 8)) | (exHeadBuf[3] & 0xFF));
	                byte[] exHeadData = new byte[exHeadLength + 4];
	                System.arraycopy(exHeadBuf, 0, exHeadData, 4, exHeadLength);
	                fs.read(exHeadData, 4, exHeadLength);
	                fsPos += exHeadLength;
	                //No use for this data in the pic so just ignore it
	            }
	            ver2 = false;
	        }
	        
	        for (boolean flag = true; (fsPos < dataLength) && flag; )
	        {
	        	//Get the frame header and make sure that it is a valid frame.
	            byte[] fBuf = new byte[ver2 ? 6 : 10];
	            if ((fs.read(fBuf, 0, fBuf.length) != fBuf.length) || ((fBuf[0] & 0xFF) <= 0))
	            {
	                flag = false;
	                continue;
	            }
	            fsPos += fBuf.length;
	            String frameId = new String(fBuf, 0, ver2 ? 3 : 4, "UTF-8");
	            destinationArray = new byte[ver2 ? 3 : 4];
	            System.arraycopy(fBuf, destinationArray.length, destinationArray, 0, destinationArray.length);
	            int frameCount = 0;
	            switch (majorVersion)
	            {
	                case 2:
	                	//24bit
	                    frameCount = ((((destinationArray[0] & 0xFF) << 0x10) | ((destinationArray[1] & 0xFF) << 8)) | (destinationArray[2] & 0xFF));
	                    break;
	                case 3:
	                	//32bit
	                    frameCount = (((((destinationArray[0] & 0xFF) << 0x18) | ((destinationArray[1] & 0xFF) << 0x10)) | ((destinationArray[2] & 0xFF) << 8)) | (destinationArray[3] & 0xFF));
	                    break;
	                case 4:
	                	//28bit
	                    frameCount = (((((destinationArray[0] & 0xFF) << 0x15) | ((destinationArray[1] & 0xFF) << 14)) | ((destinationArray[2] & 0xFF) << 7)) | (destinationArray[3] & 0xFF));
	                    break;
	                default:
	                    continue;
	            }
	            //Now read the data and check to see if it is a picture
	            fBuf = new byte[frameCount];
	            if (fs.read(fBuf, 0, frameCount) == frameCount)
	            {
	            	fsPos += frameCount;
	            	if (frameId.equals("PIC") || frameId.equals("APIC"))
	            	{
	            		//Got the frame data
	                    int refPoint = 0;
	                    //First we get the encoding type
	                    int encType = (fBuf[refPoint++] & 0xFF); //0=ISO8859, 1=Unicode,2=UnicodeBE,3=UTF8
	                    //Second we get the mime type
	                    int indexPoint = refPoint;
	                    while (fBuf[refPoint++] != 0)
	                    {
	                    }
	                    int mimeLength = refPoint - indexPoint;
	                    if (mimeLength > 1)
	                    {
	                        mimeType = new String(fBuf, indexPoint, mimeLength - 1, "ISO-8859-1");
	                    }
	                    //Third we get the picture type
	                    int picType = (fBuf[refPoint++] & 0xFF);
	                    //Fourth we load the picture description
	                    byte[] desBuf;
	                    
	                    
	                    //Finally, THE MAIN EVENT, the image data
	                    int imCount = fBuf.length - refPoint;
	                    imageData = new byte[imCount];
	                    System.arraycopy(fBuf, refPoint, imageData, 0, imCount);
	                    foundImage = true;
	                    break;
	            	}
	            }
	            continue;
	        }
	        fs.reset();
	        continue;
	    }
	    if (imageData != null)
	    {
	    	return createImageIcon(imageData);
	    }
	    //No image found
	    mimeType = null;
	    return null;
	}
	
	private ImageIcon[] generateImages(String artist, String album) throws Exception {
		URL url = new URL("https://ajax.googleapis.com/ajax/services/search/images?" +
                "v=1.0&q="+artist+"+"+album+"+Album+Cover&rsz=8");
		URLConnection connection = url.openConnection();
		connection.addRequestProperty("Referer", "http://www.bexhillweb.co.uk");
		
		String line;
		StringBuilder builder = new StringBuilder();
		BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		while((line = reader.readLine()) != null) {
			builder.append(line);
		}
		
		JSONObject json = new JSONObject(builder.toString());
		//System.out.println(json.toString());
		JSONArray results = json.getJSONObject("responseData").getJSONArray("results");
		
		String imageUrl = "";
		ImageIcon[] images = new ImageIcon[results.length()];
		for(int i=0; i<results.length();i++){
			imageUrl = results.getJSONObject(i).getString("url") == null ? "no url available" : 
				results.getJSONObject(i).getString("url");
			images[i] = createImageIcon(imageUrl);
			//System.out.println(imageUrl);
		}
		
        // get the URL to the amazon image (if one was returned).
       // String url = response.getItems().get(0).getItem().get(0).getLargeImage().getURL();

        // create an ImageIcon from the returned URL. if the URL is null, then
        // the icon returned will also be null.
		
		
		
		return images;
	}

    private ImageIcon createImageIcon(String url) {

        ImageIcon newIcon = null;

        try {
        	
        	
        	if(url == null){
        		newIcon = null;
        	} else {
	        	ImageIcon tempIcon = new ImageIcon(new URL(url));
	        	Image img = tempIcon.getImage();
	        	
	        	Image newimg = img.getScaledInstance(100, 100,  java.awt.Image.SCALE_SMOOTH);  
	        	newIcon = new ImageIcon(newimg);  
	        	
	        	/**
	        	BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
	        	Graphics g = bi.createGraphics();
	        	g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
	        	newIcon = new ImageIcon(bi);*/
        	}
            
        } catch (MalformedURLException e) {
            // do nothing - don't care.
        }

        return newIcon;
    }
    
    private ImageIcon createImageIcon(byte[] imgData) {

        ImageIcon icon = new ImageIcon(imgData);
        return icon;
    }
    
}
